﻿using System;
using System.Collections.Generic;
using System.Dynamic;
using System.IO;
using System.Linq;
using System.Text;
using System.Web;
using System.Xml;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Extensions;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using FineUICore;
using System.Reflection;
using Microsoft.AspNetCore.Mvc.Filters;
using Kalman;
using Kalman.Extensions;
using AliyunOss;
using QuDao;
using NLog;
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.Formats;
using Image = SixLabors.ImageSharp.Image;
using SixLabors.ImageSharp.Processing;
using SixLabors.ImageSharp.Formats.Gif;
using SixLabors.ImageSharp.Formats.Jpeg;
using SixLabors.ImageSharp.Formats.Png;
using RestSharp;
using System.Net;
using Kalman.Security;
using Aliyun.OSS;

namespace AdminUI
{
    public class BaseModel : PageModel
    {
        /// <summary>
        /// 后台应用名称
        /// </summary>
        protected readonly static string APP_NAME = "QuDaoAdmin";

        /// <summary>
        /// 运行的图片文件类型
        /// </summary>
        protected readonly static List<string> ALLOW_IMAGE_TYPES = new() { "jpg", "bmp", "gif", "jpeg", "png" };
        /// <summary>
        /// 无页面权限提示消息
        /// </summary>
        public static readonly string NO_PAGE_POWER_MSG = "您无权访问此页面！";
        /// <summary>
        /// 无操作权限提示消息
        /// </summary>
        public static readonly string NO_ACTION_POWER_MSG = "您无权进行此操作！";

        private DynamicViewData _viewBag;

        /// <summary>
        /// Add ViewBag to PageModel
        /// https://forums.asp.net/t/2128012.aspx?Razor+Pages+ViewBag+has+gone+
        /// https://github.com/aspnet/Mvc/issues/6754
        /// </summary>
        public dynamic ViewBag
        {
            get
            {
                _viewBag ??= new DynamicViewData(ViewData);
                return _viewBag;
            }
        }

        /// <summary>
        /// 是否页面回发
        /// </summary>
        public bool IsPostBack
        {
            get
            {
                return FineUICore.PageContext.IsFineUIAjaxPostBack();
            }
        }

        /// <summary>
        /// 注册客户端脚本
        /// </summary>
        /// <param name="scripts"></param>
        public void RegisterStartupScript(string scripts)
        {
            FineUICore.PageContext.RegisterStartupScript(scripts);
        }

        /// <summary>
        /// 获取回发的目标控件
        /// </summary>
        /// <returns></returns>
        public string GetRequestEventTarget()
        {
            return Request.Form["__EVENTTARGET"];
        }

        /// <summary>
        /// 获取回发的参数
        /// </summary>
        /// <returns></returns>
        public string GetRequestEventArgument()
        {
            return Request.Form["__EVENTARGUMENT"];
        }

        /// <summary>
        /// 获取回发的参数列表
        /// </summary>
        /// <returns></returns>
        public string[] GetRequestEventArguments()
        {
            var arg = GetRequestEventArgument();
            return arg.Split("$");
        }

        ///// <summary>
        ///// 页面处理器调用之前执行
        ///// </summary>
        ///// <param name="context"></param>
        //public override void OnPageHandlerExecuting(PageHandlerExecutingContext context)
        //{
        //    base.OnPageHandlerExecuting(context);

        //    // 如果用户已经登录，更新在线记录
        //    //if (User.Identity.IsAuthenticated)
        //    //{
        //    //    UpdateOnlineUser(GetIdentityID());
        //    //}
        //}

        public override void OnPageHandlerExecuted(PageHandlerExecutedContext context)
        {
            base.OnPageHandlerExecuted(context);

            var ex = context.Exception;
            if (ex != null)
            {
                var log = LogManager.GetCurrentClassLogger();
                var msg = ex.ToString();
                if ((ex is AppException) || (ex.InnerException != null && ex.InnerException is AppException))
                {
                    msg = ex.InnerException == null ? ex.Message : ex.InnerException.Message;
                }
                log.Error($"出错页面：{context.ActionDescriptor.RelativePath}，错误信息：{msg}");
                //context.ExceptionHandled = true;  
                //RedirectToPage("Error");
            }


            //if (context.Exception != null)
            //{
            //    var log = LogManager.GetCurrentClassLogger();
            //    if (ex is AppException)
            //    {
            //        //ShowNotify(ex.Message, MessageBoxIcon.Error);
            //        //context.ExceptionHandled = true;
            //        if (ex.InnerException == null)
            //        {
            //            log.Error(ex, $"出错页面：{context.ActionDescriptor.RelativePath}");
            //        }
            //        else
            //        {
            //            log.Error(ex.InnerException, $"{ex.Message}，出错页面：{context.ActionDescriptor.RelativePath}");
            //        }
            //    }
            //    else
            //    {
            //        if (ex.InnerException != null && ex.InnerException is AppException)
            //        {
            //            log.Error(ex.InnerException, $"{ex.Message}，出错页面：{context.ActionDescriptor.RelativePath}");
            //        }
            //        else
            //        {
            //            log.Error(ex, $"出错页面：{context.ActionDescriptor.RelativePath}");
            //        }
            //    }
            //}
        }


        public void LogAction(ActionType actionType, string memo = "")
        {
            var dto = new ActionLogAddDto
            {
                TID = OnlineTID,
                TenantName = OnlineTenantName,
                ActionType = actionType.ToString(),
                UserID = OnlineUserID,
                UserName = OnlineUserName,
                TrueName = OnlineTrueName,
                Memo = memo,
            };
            
            try
            {
                dto.ClientIP = HttpContext.Connection.RemoteIpAddress.MapToIPv4().ToString();
                dto.ModuleUrl = Request.Path.ToString();
                ActionLogBO.Instance.Add(dto);
            }
            catch (Exception ex)
            {
                var log = LogManager.GetCurrentClassLogger();
                log.Error(ex, $"记录操作日志失败：{dto.ToJson()}");
            }
        }

        #region 图片文件上传
        ///// <summary>
        ///// 上传文件到Oss
        ///// </summary>
        ///// <param name="fileType">文件类型：image-图片（默认），video-视频，audio-音频，other-其他文件</param>
        ///// <returns></returns>
        //protected Farmstay.File UploadFile(AliyunOssClient oss, IFormFile file, string fileType = "image", string memo = "")
        //{
        //    if (file == null) return null;

        //    var fileID = FileBO.GetNewID();
        //    var extName = Path.GetExtension(file.FileName);
        //    var ossKey = $"farmstay/{fileType}-{DateTime.Now:yyyyMM}/{fileID}{extName}";
        //    var entity = new Farmstay.File
        //    {
        //        FileID = fileID,
        //        FileType = fileType,
        //        FileSize = (int)file.Length,
        //        OssKey = ossKey,
        //        OssUrl = $"https://{oss.Options.DefaultBucketName}.{oss.Options.EndPoint}/{ossKey}",
        //        CreateTime = DateTime.Now,
        //        Memo = memo
        //    };

        //    using (var stream = file.OpenReadStream())
        //    {
        //        entity.HashCode = fileType switch
        //        {
        //            "image" => oss.PutImage(entity.OssKey, stream),
        //            _ => oss.PubObject(entity.OssKey, stream),
        //        };
        //    }

        //    FileBO.Instance.Add(entity);
        //    return entity;
        //}

        /// <summary>
        /// 将处理后的图片转为base64格式字符串
        /// </summary>
        /// <param name="file"></param>
        /// <param name="maxWidth">限制上传图片最大宽度，超出会自动按最大宽度裁剪</param>
        public string Image2Base64(IFormFile file, int maxWidth = 1200)
        {
            if (file == null) throw new AppException("无效的图片文件");
            if (maxWidth < 100 || maxWidth > 1500) throw new AppException("最大宽度数值无效，取值范围在100-1500之间");

            using var stream = file.OpenReadStream();
            using var img = Image.Load(stream);

            var format = img.Metadata.DecodedImageFormat;
            var width = img.Width;
            var height = img.Height;
            if (width > maxWidth) //自动转换图片大小
            {
                width = maxWidth;
                height = height * maxWidth / img.Width;
                img.Mutate(o =>
                {
                    o.Resize(width, height);
                });
            }

            var base64 = img.ToBase64String(format);
            if (base64.Length > 2 * 1024 * 1024) throw new AppException("图片转换后尺寸超过2M，请将原图进行适当压缩");

            return base64;
        }

        /// <summary>
        /// 上传文件到本地服务器
        /// </summary>
        /// <param name="file"></param>
        /// <param name="maxSize">限制上传文件的最大尺寸，默认20M</param>
        /// <returns>返回上传文件保存在服务器上的相对路径，例如：“~/upload/2987209564161.jpg”</returns>
        /// <exception cref="AppException"></exception>
        public string UploadFile(IFormFile file, int maxSize = 20)
        {
            var maxLength = maxSize * 1024 * 1024; //
            if (file == null) throw new AppException("无效的文件");
            if (file.Length > maxLength) throw new AppException($"上传文件大小不能超过{maxSize}兆");

            var fileID = IDGenerator.Instance.GetFileID();
            var extName = Path.GetExtension(file.FileName); //例如：.jpg
            var path = $"~/upload/{fileID}{extName}"; //上传文件保存在服务器上的相对路径

            using (var stream = new FileStream(FineUICore.PageContext.MapWebPath(path), FileMode.Create))
            {
                file.CopyTo(stream);
            }

            return path;
        }

        /// <summary>
        /// 上传图片
        /// </summary>
        /// <param name="file"></param>
        /// <param name="maxWidth">限制上传图片最大宽度（默认1080），超出会自动按最大宽度裁剪</param>
        public FileDto UploadImage(AliyunOssClient oss, IFormFile file, int maxWidth = 1080)
        {
            if (file == null) throw new AppException("无效的图片文件");
            if (maxWidth < 100 || maxWidth > 1500) throw new AppException("最大宽度数值无效，取值范围在100-1500之间");

            var fileID = IDGenerator.Instance.GetFileID();
            var extName = Path.GetExtension(file.FileName);

            var entity = new FileDto
            {
                FileID = fileID,
                FileSize = file.Length
            };

            using (var stream = file.OpenReadStream())
            {
                //using var img = Image.Load(stream, out IImageFormat format);
                using var img = Image.Load(stream);
                var format = img.Metadata.DecodedImageFormat;
                entity.Width = img.Width;
                entity.Height = img.Height;
                if (entity.Width > maxWidth) //自动转换图片大小
                {
                    entity.Width = maxWidth;
                    entity.Height = entity.Height * maxWidth / img.Width;
                    img.Mutate(o =>
                    {
                        o.Resize(entity.Width, entity.Height);
                    });
                }

                using var ms = new MemoryStream();
                switch (format)
                {
                    case GifFormat:
                        extName = ".gif";
                        img.SaveAsGif(ms);
                        break;
                    case JpegFormat:
                        extName = ".jpg";
                        img.SaveAsJpeg(ms, new JpegEncoder { Quality = 75 });
                        break;
                    case PngFormat:
                        extName = ".png";
                        img.SaveAsPng(ms, new PngEncoder { CompressionLevel = PngCompressionLevel.DefaultCompression });//默认Level6压缩级别
                        break;
                    default:
                        extName = ".png";
                        img.Save(ms, new PngEncoder { CompressionLevel = PngCompressionLevel.DefaultCompression });//默认Level6压缩级别
                        break;
                }
                ms.Seek(0, SeekOrigin.Begin);

                entity.OssKey = $"qudao/image-{DateTime.Now:yyyyMM}/{fileID}{extName}";
                entity.OssUrl = oss.Options.BindDomainUrl + entity.OssKey;
                entity.FileSize = ms.Length;
                entity.HashCode = oss.PutImage(entity.OssKey, ms);
            }

            return entity;
        }

        /// <summary>
        /// 上传本地图片
        /// </summary>
        /// <param name="path">本地图片路径</param>
        /// <param name="maxWidth">限制上传图片最大宽度（默认1080），超出会自动按最大宽度裁剪</param>
        public FileDto UploadLocalImage(AliyunOssClient oss, string path, int maxWidth = 1080)
        {
            if (!System.IO.File.Exists(path)) throw new AppException("图片文件不存在");
            if (maxWidth < 100 || maxWidth > 1500) throw new AppException("最大宽度数值无效，取值范围在100-1500之间");

            var fileID = IDGenerator.Instance.GetFileID();
            var extName = Path.GetExtension(path);

            var entity = new FileDto
            {
                FileID = fileID,
            };

            using (var stream = System.IO.File.OpenRead(path))
            {
                //using var img = Image.Load(stream, out IImageFormat format);
                using var img = Image.Load(stream);
                var format = img.Metadata.DecodedImageFormat;
                entity.Width = img.Width;
                entity.Height = img.Height;
                if (entity.Width > maxWidth) //自动转换图片大小
                {
                    entity.Width = maxWidth;
                    entity.Height = entity.Height * maxWidth / img.Width;
                    img.Mutate(o =>
                    {
                        o.Resize(entity.Width, entity.Height);
                    });
                }

                using var ms = new MemoryStream();
                switch (format)
                {
                    case GifFormat:
                        extName = ".gif";
                        img.SaveAsGif(ms);
                        break;
                    case JpegFormat:
                        extName = ".jpg";
                        img.SaveAsJpeg(ms, new JpegEncoder { Quality = 75 });
                        break;
                    case PngFormat:
                        extName = ".png";
                        img.SaveAsPng(ms, new PngEncoder { CompressionLevel = PngCompressionLevel.DefaultCompression });//默认Level6压缩级别
                        break;
                    default:
                        extName = ".png";
                        img.Save(ms, new PngEncoder { CompressionLevel = PngCompressionLevel.DefaultCompression });//默认Level6压缩级别
                        break;
                }
                ms.Seek(0, SeekOrigin.Begin);

                entity.OssKey = $"qudao/image-{DateTime.Now:yyyyMM}/{fileID}{extName}";
                entity.OssUrl = oss.Options.BindDomainUrl + entity.OssKey;
                entity.FileSize = ms.Length;
                entity.HashCode = oss.PutImage(entity.OssKey, ms);
            }

            return entity;
        }

        /// <summary>
        /// 上传图片
        /// </summary>
        /// <param name="file"></param>
        /// <param name="maxWidth">限制上传图片最大宽度（默认1080），超出会自动按最大宽度裁剪</param>
        public FileDto UploadRemoteImage(AliyunOssClient oss, string imageUrl, int maxWidth = 1080)
        {
            if (maxWidth < 100 || maxWidth > 1500) throw new AppException("最大宽度数值无效，取值范围在100-1500之间");

            var client = new RestClient();
            var request = new RestRequest(imageUrl);
            var response = client.Execute(request);
            if (response.StatusCode != HttpStatusCode.OK) return null;

            var data = response.RawBytes;
            if (data == null || data.Length == 0) return null;

            var fileID = IDGenerator.Instance.GetFileID();
            var extName = Path.GetExtension(imageUrl);

            var entity = new FileDto
            {
                FileID = fileID,
                FileSize = data.Length
            };

            //var s = UTF8Encoding.UTF8.GetString(data);

            using (var stream = new MemoryStream(data))
            {
                //using var img = Image.Load(stream, out IImageFormat format);
                using var img = Image.Load(stream);
                var format = img.Metadata.DecodedImageFormat;
                entity.Width = img.Width;
                entity.Height = img.Height;
                if (entity.Width > maxWidth) //自动转换图片大小
                {
                    entity.Width = maxWidth;
                    entity.Height = entity.Height * maxWidth / img.Width;
                    img.Mutate(o =>
                    {
                        o.Resize(entity.Width, entity.Height);
                    });
                }

                using var ms = new MemoryStream();
                switch (format)
                {
                    case GifFormat:
                        extName = ".gif";
                        img.SaveAsGif(ms);
                        break;
                    case JpegFormat:
                        extName = ".jpg";
                        img.SaveAsJpeg(ms, new JpegEncoder { Quality = 75 });
                        break;
                    case PngFormat:
                        extName = ".png";
                        img.SaveAsPng(ms, new PngEncoder { CompressionLevel = PngCompressionLevel.DefaultCompression });//默认Level6压缩级别
                        break;
                    default:
                        extName = ".png";
                        img.Save(ms, new PngEncoder { CompressionLevel = PngCompressionLevel.DefaultCompression });//默认Level6压缩级别
                        break;
                }
                ms.Seek(0, SeekOrigin.Begin);

                entity.OssKey = $"qudao/image-{DateTime.Now:yyyyMM}/{fileID}{extName}";
                entity.OssUrl = oss.Options.BindDomainUrl + entity.OssKey;
                entity.FileSize = ms.Length;
                entity.HashCode = oss.PutImage(entity.OssKey, ms);
            }

            return entity;
        }

        /// <summary>
        /// 上传图标（这里只是将图标图片转为base64格式）
        /// </summary>
        /// <param name="file"></param>
        /// <param name="maxSize">限制上传图标文件最大尺寸，单位：KB</param>
        public FileDto UploadIcon(IFormFile file, int maxSize = 20)
        {
            var maxLength = maxSize * 1024; //
            if (file == null) throw new AppException("无效的图标文件");
            if (file.Length > maxLength) throw new AppException($"图标文件大小不能超过{maxSize}K");

            var fileID = IDGenerator.Instance.GetFileID();

            var entity = new FileDto
            {
                FileID = fileID,
                FileName = System.IO.Path.GetFileNameWithoutExtension(file.FileName),
                FileSize = file.Length
            };

            using (var stream = file.OpenReadStream())
            {
                //using var img = Image.Load(stream, out IImageFormat format);
                using var img = Image.Load(stream);
                var format = img.Metadata.DecodedImageFormat;
                entity.Width = img.Width;
                entity.Height = img.Height;

                switch (format)
                {
                    case GifFormat:
                        entity.ExtName = "gif";
                        break;
                    case JpegFormat:
                        entity.ExtName = "jpg";
                        break;
                    case PngFormat:
                        entity.ExtName = "png";
                        break;
                    default:
                        throw new AppException("图标文件仅支持png,jpg,gif三种格式");
                }

                entity.OssUrl = img.ToBase64String(format);
            }

            return entity;
        }

        /// <summary>
        /// 上传视频文件
        /// </summary>
        /// <param name="oss"></param>
        /// <param name="file"></param>
        /// <param name="maxSize">文件大小限制，单位：兆</param>
        /// <returns></returns>
        public FileDto UploadVideo(AliyunOssClient oss, IFormFile file, int maxSize = 20)
        {
            var maxLength = maxSize * 1024 * 1024; //
            if (file == null) throw new AppException("无效的视频文件");
            if (file.Length > maxLength) throw new AppException($"视频文件大小不能超过{maxSize}兆");

            var fileID = IDGenerator.Instance.GetFileID();
            var extName = Path.GetExtension(file.FileName);

            var entity = new FileDto
            {
                FileID = fileID,
                FileSize = file.Length
            };

            using (var stream = file.OpenReadStream())
            {
                entity.OssKey = $"qudao/video-{DateTime.Now:yyyyMM}/{fileID}{extName}";
                entity.OssUrl = oss.Options.BindDomainUrl + entity.OssKey;
                entity.FileSize = stream.Length;
                entity.HashCode = oss.PubObject(entity.OssKey, stream);
            }

            return entity;
        }

        ///// <summary>
        ///// 批量上传文件到Oss
        ///// </summary>
        ///// <param name="fileType">文件类型：image-图片（默认），video-视频，audio-音频，other-其他文件</param>
        ///// <returns></returns>
        //protected List<Farmstay.File> UploadBatch(AliyunOssClient oss, IEnumerable<IFormFile> files, string fileType = "image", string memo = "")
        //{
        //    var list = new List<Farmstay.File>();
        //    if (!files.Any()) return list;

        //    foreach (var file in files)
        //    {
        //        var fileID = FileBO.GetNewID();
        //        var extName = Path.GetExtension(file.FileName);
        //        var ossKey = $"farmstay/{fileType}-{DateTime.Now:yyyyMM}/{fileID}{extName}";
        //        var entity = new Farmstay.File
        //        {
        //            FileID = fileID,
        //            FileType = fileType,
        //            FileSize = (int)file.Length,
        //            OssKey = ossKey,
        //            OssUrl = $"https://{oss.Options.DefaultBucketName}.{oss.Options.EndPoint}/{ossKey}",
        //            CreateTime = DateTime.Now,
        //            Memo = memo
        //        };

        //        using var stream = file.OpenReadStream();
        //        entity.HashCode = fileType switch
        //        {
        //            "image" => oss.PutImage(entity.OssKey, stream),
        //            _ => oss.PubObject(entity.OssKey, stream),
        //        };

        //        list.Add(entity);
        //    }

        //    FileBO.Instance.BulkInsert(list);
        //    return list;
        //}

        /// <summary>
        /// 批量上传图片
        /// </summary>
        /// <param name="files"></param>
        /// <param name="maxWidth">限制上传图片最大宽度（默认1080），超出会自动按最大宽度裁剪</param>
        /// <param name="memo">备注</param>
        public List<FileDto> UploadImageBatch(AliyunOssClient oss, List<IFormFile> files, int maxWidth = 1080)
        {
            if (files == null || files.Count < 1) throw new AppException("图片文件不能为空");
            if (maxWidth < 100 || maxWidth > 1500) throw new AppException("最大宽度数值无效，取值范围在100-1200之间");

            var list = new List<FileDto>();
            foreach (var file in files)
            {
                var fileID = IDGenerator.Instance.GetFileID();
                var extName = Path.GetExtension(file.FileName);
                var entity = new FileDto
                {
                    FileID = fileID,
                    FileSize = (int)file.Length
                };

                using (var stream = file.OpenReadStream())
                {
                    //using var img = Image.Load(stream, out IImageFormat format);
                    using var img = Image.Load(stream);
                    var format = img.Metadata.DecodedImageFormat;
                    entity.Width = img.Width;
                    entity.Height = img.Height;
                    if (entity.Width > maxWidth) //自动转换图片大小
                    {
                        entity.Width = maxWidth;
                        entity.Height = entity.Height * maxWidth / img.Width;
                        img.Mutate(o =>
                        {
                            o.Resize(entity.Width, entity.Height);
                        });
                    }

                    using var ms = new MemoryStream();
                    switch (format)
                    {
                        case GifFormat:
                            extName = ".gif";
                            img.SaveAsGif(ms);
                            break;
                        case JpegFormat:
                            extName = ".jpg";
                            img.SaveAsJpeg(ms, new JpegEncoder { Quality = 75 });
                            break;
                        case PngFormat:
                            extName = ".png";
                            img.SaveAsPng(ms, new PngEncoder { CompressionLevel = PngCompressionLevel.DefaultCompression });//默认Level6压缩级别
                            break;
                        default:
                            extName = ".png";
                            img.Save(ms, new PngEncoder { CompressionLevel = PngCompressionLevel.DefaultCompression });//默认Level6压缩级别
                            break;
                    }
                    ms.Seek(0, SeekOrigin.Begin);

                    entity.OssKey = $"qudao/image-{DateTime.Now:yyyyMM}/{fileID}{extName}";
                    entity.OssUrl = oss.Options.BindDomainUrl + entity.OssKey;
                    entity.FileSize = (int)ms.Length;
                    entity.HashCode = oss.PutImage(entity.OssKey, ms);
                }

                list.Add(entity);
            }

            return list;
        }

        /// <summary>
        /// 上传Html内容
        /// </summary>
        /// <param name="html">备注</param>
        public string UploadHtml(AliyunOssClient oss, string html)
        {
            var fileID = IDGenerator.Instance.GetFileID();
            var ossKey = $"qudao/html-{DateTime.Now:yyyyMM}/{fileID}.html";

            oss.PutString(ossKey, html, ContentType.TEXT_HTML);
            return ossKey;
        }

        #endregion

        #region 公用方法

        /// <summary>
        /// 上传文件类型判断
        /// </summary>
        /// <param name="fileName"></param>
        /// <returns></returns>
        protected static bool ValidateFileType(string fileName)
        {
            string fileType = String.Empty;
            int lastDotIndex = fileName.LastIndexOf(".");
            if (lastDotIndex >= 0)
            {
                fileType = fileName[(lastDotIndex + 1)..].ToLower();
            }

            if (ALLOW_IMAGE_TYPES.Contains(fileType))
            {
                return true;
            }
            else
            {
                return false;
            }
        }


        /// <summary>
        /// 获取当前应用的版本号
        /// </summary>
        /// <returns></returns>
        protected string GetVersion()
        {
            Version v = Assembly.GetExecutingAssembly().GetName().Version;
            return String.Format("{0}.{1}.{2}", v.Major, v.Minor, v.Build);
        }

        /// <summary>
        /// 显示通知对话框
        /// </summary>
        public virtual void ShowNotify(string message)
        {
            ShowNotify(message, MessageBoxIcon.Information);
        }

        /// <summary>
        /// 显示通知对话框
        /// </summary>
        public virtual void ShowNotify(string message, MessageBoxIcon messageIcon)
        {
            ShowNotify(message, messageIcon, Target.Top);
        }

        /// <summary>
        /// 显示通知对话框
        /// </summary>
        public virtual void ShowNotify(string message, MessageBoxIcon messageIcon, Target target)
        {
            var n = new Notify
            {
                Target = target,
                Message = message,
                MessageBoxIcon = messageIcon,
                PositionX = Position.Center,
                PositionY = Position.Top,
                DisplayMilliseconds = 3000,
                ShowHeader = false
            };

            n.Show();
        }

        /// <summary>
        /// 获取网址的完整路径
        /// </summary>
        /// <param name="virtualPath"></param>
        /// <returns></returns>
        public string GetAbsoluteUrl(string virtualPath)
        {
            // http://benjii.me/2015/05/get-the-absolute-uri-from-asp-net-mvc-content-or-action/
            var urlBuilder = new System.UriBuilder(Request.GetDisplayUrl())
            {
                Path = Url.Content(virtualPath),
                Query = null,
            };

            return urlBuilder.ToString();
        }

        /// <summary>
        /// 加载XML文件
        /// </summary>
        /// <param name="xmlPath"></param>
        /// <returns></returns>
        protected XmlDocument LoadXml(string xmlPath)
        {
            // 加载XML配置文件
            xmlPath = FineUICore.PageContext.MapPath(xmlPath);
            string xmlContent = string.Empty;
            using (var sr = new StreamReader(xmlPath))
            {
                xmlContent = sr.ReadToEnd();
            }

            var doc = new XmlDocument();
            doc.LoadXml(xmlContent);

            return doc;
        }

        #endregion

        #region 公用数据
        /// <summary>
        /// 栏目类型数据列表
        /// </summary>
        public List<NameValueDto> ColumnTypeList
        {
            get
            {
                return new List<NameValueDto>
                {
                    new NameValueDto { Name = "== 请选择栏目类型 ==", Value = "0" },
                    //new NameValueDto { Name = "系统版块", Value = "99" },
                    new NameValueDto { Name = "新闻资讯", Value = "10" },
                    new NameValueDto { Name = "游玩攻略", Value = "11" },
                    new NameValueDto { Name = "土地流转", Value = "12" },
                    new NameValueDto { Name = "农房租赁", Value = "13" },
                    new NameValueDto { Name = "招商合作", Value = "14" }
                };
            }
        }

        /// <summary>
        /// 相册类型数据列表（相册类型：1-租户，2-村庄，3-商品，4-门店，5-房型，6-文章，7-农场）
        /// </summary>
        public List<NameValueDto> AlbumTypeList
        {
            get
            {
                return new List<NameValueDto>
                {
                    new NameValueDto { Name = "== 请选择相册类型 ==", Value = "0" },
                    new NameValueDto { Name = "租户", Value = "1" },
                    new NameValueDto { Name = "村庄", Value = "2" },
                    new NameValueDto { Name = "商品", Value = "3" },
                    new NameValueDto { Name = "门店", Value = "4" },
                    new NameValueDto { Name = "房型", Value = "5" },
                    new NameValueDto { Name = "文章", Value = "6" },
                    new NameValueDto { Name = "农场", Value = "7" },
                };
            }
        }

        /// <summary>
        /// 视频类型数据列表（视频类型：1-租户，2-动态，3-商品，4-活动，5-门店，6-慢直播，7-农场监控）
        /// </summary>
        public List<NameValueDto> VideoTypeList
        {
            get
            {
                return new List<NameValueDto>
                {
                    new NameValueDto { Name = "== 请选择视频类型 ==", Value = "0" },
                    new NameValueDto { Name = "租户", Value = "1" },
                    new NameValueDto { Name = "动态", Value = "2" },
                    new NameValueDto { Name = "商品", Value = "3" },
                    new NameValueDto { Name = "活动", Value = "4" },
                    new NameValueDto { Name = "门店", Value = "5" },
                    new NameValueDto { Name = "慢直播", Value = "6" },
                    new NameValueDto { Name = "农场监控", Value = "7" },
                };
            }
        }

        /// <summary>
        /// 服务类别：10-住宿，11-集市，12-订票，13-订餐，14-租赁，15-研学，16-团建，17-禅修，18-佛事
        /// </summary>
        public List<NameValueDto> ServiceCategoryList
        {
            get
            {
                return new List<NameValueDto>
                {
                    new NameValueDto { Name = "== 请选择服务类别 ==", Value = "0" },
                    new NameValueDto { Name = "住宿", Value = "10" },
                    new NameValueDto { Name = "集市", Value = "11" },
                    new NameValueDto { Name = "订票", Value = "12" },
                    new NameValueDto { Name = "订餐", Value = "13" },
                    new NameValueDto { Name = "租赁", Value = "14" },
                    new NameValueDto { Name = "研学", Value = "15" },
                    new NameValueDto { Name = "团建", Value = "16" },
                    new NameValueDto { Name = "禅修", Value = "17" },
                    new NameValueDto { Name = "佛事", Value = "18" },
                };
            }
        }

        /// <summary>
        /// 营业时间列表
        /// </summary>
        public List<NameValueDto> WorkingTimesList
        {
            get
            {
                var list = new List<NameValueDto>();
                for (int i = 0; i <= 24; i++)
                {
                    if(i == 0)
                    {
                        list.Add(new NameValueDto { Name = "0:00", Value = "0" });
                    }
                    else
                    {
                        list.Add(new NameValueDto { Name = $"{i}:00", Value = $"{i}00" });
                    }
                }
                return list;

            }
        }

        #endregion

        #region Session缓存

        public T GetSession<T>(string key)
        {
            return HttpContext.Session.GetObject<T>(key);
        }

        public void SetSession<T>(string key, object value)
        {
            HttpContext.Session.SetObject(key, value);
        }

		public string GetStringFromSession(string key)
		{
			return HttpContext.Session.GetString(key);
		}

		public void SetStringToSession(string key, string value)
		{
			HttpContext.Session.SetString(key, value);
		}

		public int? GetInt32FromSession(string key)
		{
			return HttpContext.Session.GetInt32(key);
		}

		public void SetInt32ToSession(string key, int value)
		{
			HttpContext.Session.SetInt32(key, value);
		}
		#endregion

		#region 用户和权限

		/// <summary>
		/// 当前登录用户ID
		/// </summary>
		public int OnlineUserID => int.Parse(GetClaimsData(HttpContext, "UserID"));
        /// <summary>
        /// 当前登录用户类型：1-平台，2-租户
        /// </summary>
        protected int OnlineUserType => int.Parse(GetClaimsData(HttpContext, "UserType"));
        /// <summary>
        /// 当前登录用户名
        /// </summary>
        /// <returns></returns>
        protected string OnlineUserName => GetClaimsData(HttpContext, "UserName");
        /// <summary>
        /// 当前登录用户姓名
        /// </summary>
        /// <returns></returns>
        protected string OnlineTrueName => GetClaimsData(HttpContext, "TrueName");
        /// <summary>
        /// 当前登录用户所拥有的角色
        /// </summary>
        protected int OnlineRoleID => int.Parse(GetClaimsData(HttpContext, "RoleID"));

        /// <summary>
        /// 当前登录用户所属租户ID
        /// </summary>
        public int OnlineTID => int.Parse(GetClaimsData(HttpContext, "TID"));
        /// <summary>
        /// 当前登录用户所属租户名称
        /// </summary>
        protected string OnlineTenantName => GetClaimsData(HttpContext, "TenantName");

        /// <summary>
        /// A级会员别名
        /// </summary>
        public string OnlineMAName => GetClaimsData(HttpContext, "MAName");
        /// <summary>
        /// B级会员别名
        /// </summary>
        public string OnlineMBName => GetClaimsData(HttpContext, "MBName");
        /// <summary>
        /// C级会员别名
        /// </summary>
        public string OnlineMCName => GetClaimsData(HttpContext, "MCName");

        /// <summary>
        /// 获取当前登录凭证相关数据
        /// </summary>
        /// <param name="claimType">ClaimType：UserID，UserName，TID，UserType，RoleID</param>
        /// <returns></returns>
        protected static string GetClaimsData(HttpContext context, string claimType)
        {
            if (!context.User.Identity.IsAuthenticated) return null;

            var val = context.User.Claims.Where(x => x.Type == claimType).FirstOrDefault().Value;
            return val;
        }

        /// <summary>
        /// 获取当前登录用户拥有的全部权限列表
        /// </summary>
        public static List<string> GetRolePowerNames(HttpContext context)
        {
            return new List<string>();
        }

        /// <summary>
        /// 检查当前用户是否拥有某个权限
        /// </summary>
        protected bool CheckPower(string powerName)
        {
            return CheckPower(HttpContext, powerName);
        }

        /// <summary>
        /// 获取当前登录用户拥有的全部权限列表
        /// </summary>
        /// <param name="roleIDs"></param>
        /// <returns></returns>
        protected List<string> GetRolePowerNames()
        {
            return GetRolePowerNames(HttpContext);
        }

        /// <summary>
        /// 检查权限失败（页面第一次加载）
        /// </summary>
        public static void CheckPowerFailWithPage(HttpContext context)
        {
            string PageTemplate = "<!DOCTYPE html><html><head><meta http-equiv=\"Content-Type\" content=\"text/html;charset=utf-8\"/><head><body>{0}</body></html>";
            context.Response.WriteAsync(String.Format(PageTemplate, NO_PAGE_POWER_MSG));
        }

        /// <summary>
        /// 检查权限失败（页面回发）
        /// </summary>
        public static void CheckPowerFailWithAlert()
        {
            FineUICore.PageContext.RegisterStartupScript(Alert.GetShowInTopReference(NO_ACTION_POWER_MSG));
        }

        /// <summary>
        /// 检查当前用户是否拥有某个权限
        /// </summary>
        /// <param name="context"></param>
        /// <param name="powerName"></param>
        /// <returns></returns>
        public static bool CheckPower(HttpContext context, string powerName)
        {
            // 如果权限名为空，则放行
            if (String.IsNullOrEmpty(powerName))
            {
                return true;
            }

            // 当前登陆用户的权限列表
            List<string> rolePowerNames = GetRolePowerNames(context);
            if (rolePowerNames.Contains(powerName))
            {
                return true;
            }

            return false;
        }

        #endregion

    }
}
